/**
 * 节流: 只在规定的时间间隔执行。 不管你滚动多少次， 只在300ms间隔执行一次
 * @type {{timer: null, process: obj.process, executor: obj.executor}}
 */

const obj = {
    timer: null,

    executor: function () {
        // 这里是想要执行的code
    },

    process: function () {
        clearTimeout(this.timer)

        // 这里的that可以使用改变this指向的call和apply来实现， 主要看的是后面参数的类型是基本数据类型还是数组类型。
        const that = this
        this.timer = setTimeout(() => {
            // 每一百秒执行一次， 再每次执行之前要关闭之前的定时器， 防止多开好多定时器
            that.executor()
        }, 100)
    }
}

// 定时器写法
// 但是这样会导致第一次没有立即执行。
function foo(executor, interval) {
    let timer = null
    let _this = this

    // 当前没有timer，再执行
    if (!timer) {
        // clearTimeout(timer) // 这里面本来就是
        this.timer = setTimeout(() => {
            // executor.call(_this,)
            _this.timer = null
        }, interval)
    }
}

function executor() {
    // 实际执行的函数
}

// foo(executor, 100)

// 时间戳写法
// 但是这样的， 会导致最后一次没有执行
function foo1(executor, interval) {
    let lastTime = 0;
    const curTime = Date.now()
    if (curTime - lastTime > interval) {
        executor.call(...arguments)
        lastTime = curTime
    }
}

// 时间戳和定时器结合
function foo2() {

}

/**
 * 定时器版本
 * @param executor
 * @param interval
 * @returns {function(...[*]=): void}
 */
function throttle(executor, interval) {
    // let _this = this
    let timer = null

    return function (...args) {
        let _this = this
        if (!timer) {
            timer = setTimeout(() => {
                executor.call(_this, args)
                timer = null
            }, interval)
        }
    }
}

function throttle2(executor, interval) {
    let previous = 0
    return function (...args) {
        let now = Date.now()
        let _this = this

        if (now - previous > interval) {
            executor.call(_this, args)
            previous = now;
        }
    }
}

throttle2(print, 30000)

function print() {
    console.log('打印数据')
}

let i = 10000;
while (i > 0) {
    print()
    i--
}

// 第一次和最后一次都执行怎么做
// 时间戳版本， 第一次能够执行。
// 定时器版本， 最后一次可以被执行。
function throttle3(fun, interval){
    let previous = 0
    let timer = null

    return function (...args){
        let _this = this
        let now = Date.now()
        let remaining = interval-(now - previous)
        clearTimeout(timer)

        if(remaining<0){
            fun.call(_this,args)
            previous  = now
        }else{
            setTimeout(()=>{
                fun.call(_this, args)
            },remaining)
        }
    }
}
